/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package managedbean.SLC;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.PostConstruct;
import javax.ejb.EJB;
import javax.faces.bean.ViewScoped;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import javax.mail.internet.AddressException;
import javax.mail.internet.InternetAddress;
import javax.servlet.http.HttpServletRequest;
import merlion.common.entity.SecurityRole;
import merlion.common.entity.Staff;
import merlion.common.session.stateless.SystemUserSessionBeanLocal;
import merlion.common.util.Consts;
import merlion.common.util.exception.NotExistException;
import merlion.crm.slcm.entity.Address;
import merlion.crm.slcm.entity.ContactRecord;
import merlion.crm.slcm.entity.SalesLead;
import merlion.crm.slcm.session.SLCSessionBeanLocal;
import org.primefaces.context.RequestContext;

/**
 *
 * @author Kenn
 */
@ManagedBean(name = "salesLeadManagerBean")
@ViewScoped
public class SalesLeadManagerBean {

    @EJB
    private SLCSessionBeanLocal sLCSessionBean;
    @EJB
    private SystemUserSessionBeanLocal userManager;
    private SalesLead salesLead;
    private ContactRecord contactRecord;
    private ContactRecord contactRecordBackup;
    private Address shippingAddress;
    private Address shippingAddressBackup;
    private Collection<SalesLead> salesLeads;
    private Staff loginUser;
    private Staff newCE;

    //----------------------------------------------------------------------
    //                  SalesLeadManagerBean Constructor
    //----------------------------------------------------------------------
    public SalesLeadManagerBean() {
        salesLead = new SalesLead();
        contactRecord = new ContactRecord();
        contactRecordBackup = new ContactRecord();
        shippingAddress = new Address();
        salesLeads = new ArrayList<SalesLead>();
        loginUser = new Staff();
    }

    @PostConstruct
    public void init() {
        salesLead.setClientId(sLCSessionBean.generateClientID());
        loginUser = (Staff) FacesContext.getCurrentInstance().getExternalContext().getSessionMap().get("app.user.name");
        // TODO: need to use id to get the staff (done)
        loginUser = userManager.getStaff(loginUser.getId());
        salesLead.setCustomerExecutive(loginUser);

        //Process view/update request
        try {
            FacesContext context = FacesContext.getCurrentInstance();
            String param = context.getExternalContext().getRequestParameterMap().get("id");
            if (param != null) {
                Long id = Long.parseLong(param);
                setSalesLead(sLCSessionBean.getSalesLeadById(id));
            }
        } catch (NotExistException ex) {
            Logger.getLogger(SalesLeadManagerBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    //--------------------------------------------------------------------------
    //                  SalesLeadManagerBean Page Controller Methods
    //--------------------------------------------------------------------------
    
    public boolean isSalesManagerOrVP(){
        for(SecurityRole sr: loginUser.getSecurityRoles()){
            if(sr.getRoleName().equals(Consts.SALES_MANAGER_ROLE) ||
               sr.getRoleName().equals(Consts.SALES_VP_ROLE) )
                return true;
        }
        return false;
    }
    
    public void addContactRecord() {

        //Validate contact record
        RequestContext context = RequestContext.getCurrentInstance();
        boolean valid = true;

        // Contact Name: Required, Alphabetic
        if (!isNotEmpty(contactRecord.getName())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Name", "cannot be empty."));
            valid = false;
        }
        if (!isAlphabetic(contactRecord.getName())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Name", "can only contain alphabetical characters."));
            valid = false;
        }

        // Contact Designation: Required, Alphabetic
        if (!isNotEmpty(contactRecord.getJobTitle())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Designation", "cannot be empty."));
            valid = false;
        }
        if (!isAlphabetic(contactRecord.getJobTitle())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Designation", "can only contain alphabetical characters."));
            valid = false;
        }

        // Contact Phone: Required
        if (!isNotEmpty(contactRecord.getPhone())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Phone", "cannot be empty."));
            valid = false;
        }

        // Contact Email: Required, is valid email
        if (!isNotEmpty(contactRecord.getEmail())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "E-mail", "cannot be empty."));
            valid = false;
        }
        if (!isValidEmailAddress(contactRecord.getEmail())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "E-mail", "is not valid."));
            valid = false;
        }
        context.addCallbackParam("valid", valid);

        if (valid) {
            salesLead.getContactRecords().add(contactRecord);
            //Reset Contact Record
            contactRecord = new ContactRecord();
        }
    }
    
    public void updateContactRecordBackup(ActionEvent event){
        
        contactRecord = (ContactRecord)event.getComponent().getAttributes().get("selectedContactRecord");
        
        contactRecordBackup = new ContactRecord();
        contactRecordBackup.setEmail(contactRecord.getEmail());
        contactRecordBackup.setId(contactRecord.getId());
        contactRecordBackup.setJobTitle(contactRecord.getJobTitle());
        contactRecordBackup.setName(contactRecord.getName());
        contactRecordBackup.setPhone(contactRecord.getPhone());
        contactRecordBackup.setTimeCreated(contactRecord.getTimeCreated());
    }

    public void updateContactRecord() {

        //Validate contact record
        RequestContext context = RequestContext.getCurrentInstance();
        boolean valid = true;

        // Contact Name: Required, Alphabetic
        if (!isNotEmpty(contactRecord.getName())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Name", "cannot be empty."));
            valid = false;
        }
        if (!isAlphabetic(contactRecord.getName())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Name", "can only contain alphabetical characters."));
            valid = false;
        }

        // Contact Designation: Required, Alphabetic
        if (!isNotEmpty(contactRecord.getJobTitle())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Designation", "cannot be empty."));
            valid = false;
        }
        if (!isAlphabetic(contactRecord.getJobTitle())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Designation", "can only contain alphabetical characters."));
            valid = false;
        }

        // Contact Phone: Required
        if (!isNotEmpty(contactRecord.getPhone())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Phone", "cannot be empty."));
            valid = false;
        }

        // Contact Email: Required, is valid email
        if (!isNotEmpty(contactRecord.getEmail())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "E-mail", "cannot be empty."));
            valid = false;
        }
        if (!isValidEmailAddress(contactRecord.getEmail())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "E-mail", "is not valid."));
            valid = false;
        }
        context.addCallbackParam("valid", valid);

        if (valid) {
            for (ContactRecord cr : salesLead.getContactRecords()) {
                if (cr.equals(contactRecord)) {
                    cr = contactRecord;
                }
            }
            //Reset contact record
            contactRecord = new ContactRecord();
        }
    }

    public void deleteContactRecord() {
        
        salesLead.getContactRecords().remove(contactRecord);

        //Reset contact record
        contactRecord = new ContactRecord();
    }

    public void resetContactRecord() {
        
        contactRecord.setName(contactRecordBackup.getName());
        contactRecord.setEmail(contactRecordBackup.getEmail());
        contactRecord.setJobTitle(contactRecordBackup.getJobTitle());
        contactRecord.setPhone(contactRecordBackup.getPhone());
        contactRecord.setTimeCreated(contactRecordBackup.getTimeCreated());
        
        contactRecord = new ContactRecord();
    }

    public void addShippingAddress() {

        RequestContext context = RequestContext.getCurrentInstance();
        boolean valid = true;

        // Address Line 1: Alphanumeric, Required
        if (!isNotEmpty(shippingAddress.getAddressLine1())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address Line 1", "cannot be empty."));
            valid = false;
        }

        // Address Line 2: Alphanumeric, Required
        if (!isNotEmpty(shippingAddress.getAddressLine2())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address Line 2", "cannot be empty."));
            valid = false;
        }

        // Zipcode: Numeric, Required
        if (!isNotEmpty(shippingAddress.getZipCode())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address Zip Code", "cannot be empty."));
            valid = false;
        }
        if (!isNumeric(shippingAddress.getZipCode())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address Zip Code", "can only contain numeric characters."));
            valid = false;
        }

        // City: Alphabetic, Required
        if (!isNotEmpty(shippingAddress.getCity())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address City", "cannot be empty."));
            valid = false;
        }
        if (!isAlphabetic(shippingAddress.getCity())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address City", "can only contain alphabetical characters."));
            valid = false;
        }

        // State: Alphabetic, Required
        if (!isNotEmpty(shippingAddress.getStateName())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address State", "cannot be empty."));
            valid = false;
        }
        if (!isAlphabetic(shippingAddress.getStateName())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address State", "can only contain alphabetical characters."));
            valid = false;
        }

        //Country: Alphabetic, Required
        if (!isNotEmpty(shippingAddress.getCountry())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address Country", "cannot be empty."));
            valid = false;
        }
        if (!isAlphabetic(shippingAddress.getCountry())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address Country", "can only contain alphabetical characters."));
            valid = false;
        }

        context.addCallbackParam("valid", valid);

        if (valid) {
            salesLead.getShippingAddress().add(shippingAddress);

            //Reset shipping address
            shippingAddress = new Address();
        }
    }

    public void updateShippingAddress() {

        RequestContext context = RequestContext.getCurrentInstance();
        boolean valid = true;

        // Address Line 1: Alphanumeric, Required
        if (!isNotEmpty(shippingAddress.getAddressLine1())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address Line 1", "cannot be empty."));
            valid = false;
        }

        // Address Line 2: Alphanumeric, Required
        if (!isNotEmpty(shippingAddress.getAddressLine2())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address Line 2", "cannot be empty."));
            valid = false;
        }

        // Zipcode: Numeric, Required
        if (!isNotEmpty(shippingAddress.getZipCode())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address Zip Code", "cannot be empty."));
            valid = false;
        }
        if (!isNumeric(shippingAddress.getZipCode())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address Zip Code", "can only contain numeric characters."));
            valid = false;
        }

        // City: Alphabetic, Required
        if (!isNotEmpty(shippingAddress.getCity())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address City", "cannot be empty."));
            valid = false;
        }
        if (!isAlphabetic(shippingAddress.getCity())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address City", "can only contain alphabetical characters."));
            valid = false;
        }

        // State: Alphabetic, Required
        if (!isNotEmpty(shippingAddress.getStateName())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address State", "cannot be empty."));
            valid = false;
        }
        if (!isAlphabetic(shippingAddress.getStateName())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address State", "can only contain alphabetical characters."));
            valid = false;
        }

        //Country: Alphabetic, Required
        if (!isNotEmpty(shippingAddress.getCountry())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address Country", "cannot be empty."));
            valid = false;
        }
        if (!isAlphabetic(shippingAddress.getCountry())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address Country", "can only contain alphabetical characters."));
            valid = false;
        }

        context.addCallbackParam("valid", valid);

        if (valid) {
            for (Address sa : salesLead.getShippingAddress()) {
                if (sa.equals(shippingAddress)) {
                    sa = shippingAddress;
                }
            }
            //Reset shipping address
            shippingAddress = new Address();
        }
    }
    
    public void updateShippingAddressBackup(ActionEvent event){
        
        shippingAddress = (Address)event.getComponent().getAttributes().get("selectedShippingAddress");
        
        shippingAddressBackup = new Address();
        shippingAddressBackup.setAddressLine1(shippingAddress.getAddressLine1());
        shippingAddressBackup.setAddressLine2(shippingAddress.getAddressLine2());
        shippingAddressBackup.setAddressType(shippingAddress.getAddressType());
        shippingAddressBackup.setCity(shippingAddress.getCity());
        shippingAddressBackup.setCountry(shippingAddress.getCountry());
        shippingAddressBackup.setStateName(shippingAddress.getStateName());
        shippingAddressBackup.setTimeCreated(shippingAddress.getTimeCreated());
        shippingAddressBackup.setZipCode(shippingAddress.getZipCode());
    }

    public void deleteShippingAddress() {
        
        salesLead.getShippingAddress().remove(shippingAddress);

        //Reset shipping address
        shippingAddress = new Address();
    }

    public void resetShippingAddress() {

        shippingAddress.setAddressLine1(shippingAddressBackup.getAddressLine1());
        shippingAddress.setAddressLine2(shippingAddressBackup.getAddressLine2());
        shippingAddress.setAddressType(shippingAddressBackup.getAddressType());
        shippingAddress.setCity(shippingAddressBackup.getCity());
        shippingAddress.setCountry(shippingAddressBackup.getCountry());
        shippingAddress.setStateName(shippingAddressBackup.getStateName());
        shippingAddress.setTimeCreated(shippingAddressBackup.getTimeCreated());
        shippingAddress.setZipCode(shippingAddressBackup.getZipCode());
        
        shippingAddress = new Address();
    }

    public String viewAllSalesLead() {
        return "/SLC/viewAllSalesLead?faces-redirect=true";
    }

    public String createSalesLead() {
        //Validate
        if (validate(salesLead)) {
            //Persist salesLead first to set autoID in SalesLead Entity during persist
            salesLead = sLCSessionBean.createSalesLead(salesLead);

            //Set customer executive-to-salesLead relation 
            salesLead.getCustomerExecutive().getSalesLeads().add(salesLead);

            // Call EJB to persist object.
            salesLead = sLCSessionBean.updateSalesLead(salesLead);

            return "confirm";
        }
        return null;
    }

    public String viewSalesLead(Long id) {
        return "viewAllSalesLeadView?id=" + id + "&faces-redirect=true";
    }

    public String updateSalesLead(Long id) {
        return "viewAllSalesLeadUpdate?id=" + id + "&faces-redirect=true";
    }

    public String saveUpdatedSalesLead() {

        // Call EJB to persist object.
        salesLead = sLCSessionBean.updateSalesLead(salesLead);

        return "confirm";
    }

    public void updateCustomerExecutive() {
        Staff currCE = salesLead.getCustomerExecutive();
        if (!newCE.equals(currCE)) {
            newCE.getSalesLeads().add(salesLead);
            currCE.getSalesLeads().remove(salesLead);
            salesLead.setCustomerExecutive(newCE);
        }
    }

    public boolean renderUpdate(SalesLead salesLead) {
        boolean render = false;
        if (salesLead.getCustomerExecutive().equals(loginUser)) {
            render = true;
        }
        for (SecurityRole sr : loginUser.getSecurityRoles()) {
            if (sr.getRoleName().equals("SalesManager") || sr.getRoleName().equals("SalesVP")) {
                render = true;
            }
        }
        return render;
    }

    public String convertSalesLead(Long id) {
        return "viewAllSalesLeadConvert?id=" + id + "&faces-redirect=true";
    }

    //--------------------------------------------------------------------------
    //             Sales Lead Manager Bean DataTable/Form Controller
    //--------------------------------------------------------------------------
    public Collection<SalesLead> getAllSalesLead() {
        setSalesLeads(sLCSessionBean.getAllSalesLead());
        return salesLeads;
    }

    //----------------------------------------------------------------------
    //            SalesLeadManagerBean Accessor and Mutator Methods
    //----------------------------------------------------------------------
    public void setSalesLead(SalesLead salesLead) {
        this.salesLead = salesLead;
    }

    public SalesLead getSalesLead() {
        return salesLead;
    }

    public void setSalesLeads(Collection<SalesLead> list) {
        this.salesLeads = list;
    }

    public Collection<SalesLead> getSalesLeads() {
        return salesLeads;
    }

    public void setLoginUser(Staff loginUser) {
        this.loginUser = loginUser;
    }

    public Staff getLoginUser() {
        return this.loginUser;
    }

    public ContactRecord getContactRecord() {
        return contactRecord;
    }

    public void setContactRecord(ContactRecord contactRecord) {
        this.contactRecord = contactRecord;
    }

    public Address getShippingAddress() {
        return shippingAddress;
    }

    public void setShippingAddress(Address shippingAddress) {
        this.shippingAddress = shippingAddress;
    }

    public Staff getNewCE() {
        return newCE;
    }

    public void setNewCE(Staff newCE) {
        this.newCE = newCE;
    }

    //-------------------------------------------------------------------------
    //              SalesLeadManager Bean Customer Validator
    //-------------------------------------------------------------------------
    private boolean isValidEmailAddress(String email) {
        if(email.matches("[\\w\\.-]*[a-zA-Z0-9_]@[\\w\\.-]*[a-zA-Z0-9]\\.[a-zA-Z][a-zA-Z\\.]*[a-zA-Z]")){
            return true;
        }
        return false;
    }


    private boolean isAlphabetic(String str) {
        if (str.matches("[a-zA-Z\\s]*")) {
            return true;
        } else {
            return false;
        }
    }

    private boolean isAlphanumeric(String str) {

        if (str.matches("[a-zA-z0-9\\s]*")) {
            return true;
        } else {
            return false;
        }

    }

    private boolean isNumeric(String str) {
        if (str.matches("[0-9]*")) {
            return true;
        } else {
            return false;
        }

    }

    private boolean isNotEmpty(String str) {
        if (str == null) {
            return false;
        }
        if (str.equals("")) {
            return false;
        }
        return true;
    }

    private boolean validate(SalesLead salesLead) {

        boolean valid = true;
        // Company Name: Required, Alphanumeric
        if (!isNotEmpty(salesLead.getCompanyName())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Company Name", "cannot be empty."));
            valid = false;
        }
        if (!isAlphanumeric(salesLead.getCompanyName())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Company Name", "can only contain alphanumeric characters."));
            valid = false;
        }

        // Category: Required
        if (!isNotEmpty(salesLead.getCategory())) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Category", "cannot be empty."));
            valid = false;
        }

        // Contact Record
        // Check has at least one contact record
        if (salesLead.getContactRecords().isEmpty()) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Contact Record List", "must contain at least one contact record"));
            valid = false;
        }

        //Shipping Address
        //Check at least one shipping address
        if (salesLead.getShippingAddress().isEmpty()) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_WARN, "Shipping Address List", "must contain at least one shipping address"));
            valid = false;
        }

        //Check for each shipping address
        for (Address sa : salesLead.getShippingAddress()) {
        }
        return valid;
    }
}
